package dev.ece.suit.hexmap;

import com.bulletphysics.collision.shapes.CollisionShape;

import dev.ece.core.cells.model.AbstractModel;
import dev.ece.core.cells.model.ModelCollisionShape;
import dev.ece.core.texture.FBOS;
import dev.ece.suit.skybox.SkyBox;
import dev.ece.util.lib.Vector3f;
import dev.ece.util.tools.Camera;

public class MapModel extends AbstractModel<Float> implements ModelCollisionShape {

	private TerrainModelCreator terrainModelCreator;
	
	private SkyBox skybox;
	
	private MapCell[][] cells;
	
	private MapCrevice[] crevices;
	
	private MapTriangle[] triangles;
	
	private MapWater[] waters;
	
	private MapCellVAO mapCellVAO;
	
	private MapCreviceVAO mapCreviceVAO;
	
	private MapTriangleVAO mapTriangleVAO;
	
	private MapWaterVAO mapWaterVAO;
	
	public MapModel(TerrainModelCreator terrainModelCreator, SkyBox skybox, int[][] terrains) {
		if(terrainModelCreator == null) {
			throw new IllegalArgumentException("terrainModelCreator不能为null");
		}
//		if(skybox == null) {
//			throw new IllegalArgumentException("skybox不能为null");
//		}
		if(terrains == null) {
			throw new IllegalArgumentException("terrains不能为null");
		}
		this.terrainModelCreator = terrainModelCreator;
		this.skybox = skybox;
		this.setup(terrains);
	}
	
	protected void setup(int[][] terrains) {
		cells = getTerrainModelCreator().createMapCells(terrains);
		crevices = getTerrainModelCreator().createMapCrevices(cells);
		triangles = getTerrainModelCreator().createMapTriangles(cells);
		waters = getTerrainModelCreator().createMapWaters(cells);
		mapCellVAO = createMapCellVAO();
		mapCreviceVAO = createMapCreviceVAO();
		mapTriangleVAO = createMapTriangleVAO();
		mapWaterVAO = createMapWaterVAO();
	}
	
	protected MapWaterVAO createMapWaterVAO() {
		return MapWaterVAO.createMapWaterVAO(getCells());
	}
	
	protected MapTriangleVAO createMapTriangleVAO() {
		return null;
	}
	
	protected MapCreviceVAO createMapCreviceVAO() {
		return MapCreviceVAO.createMapCreviceVAO(getTerrainModelCreator(), getCrevices());
	}
	
	protected MapCellVAO createMapCellVAO() {
		return MapCellVAO.createMapCellVAO(getTerrainModelCreator(), getCells());
	}
	
	@Override
	public void onInitialize() {
		getMapCellVAO().initialize();
		getMapCreviceVAO().initialize();
		//getMapTriangleVAO().initialize();
		//getMapWaterVAO().initialize();
	}
	
	@Override
	public void destroy() {
		getMapCellVAO().destroy();
		getMapCreviceVAO().destroy();
		//getMapTriangleVAO().destroy();
		//getMapWaterVAO().destroy();
		
		terrainModelCreator = null;
		skybox = null;
		cells = null;
		crevices = null;
		triangles = null;
		waters = null;
		mapCellVAO = null;
		mapCreviceVAO = null;
		mapTriangleVAO = null;
		mapWaterVAO = null;
	}

	@Override
	public void onRenderDepthMap(Camera camera, Float value) {
		MapCell[] cols = null;
		getMapCellVAO().bind();
		for(int row = 0; row < getCells().length; row ++) {
			cols = getCells()[row];
			for(int col = 0; col < cols.length; col ++) {
				cols[col].renderDepth(this);
			}
		}
		getMapCreviceVAO().bind();
		for(int i=0; i<getCrevices().length; i++) {
			getCrevices()[i].renderDepth(this);
		}
//		getMapTriangleVAO().bind();
//		for(int i=0; i<getTriangles().length; i++) {
//			getTriangles()[i].renderDepth(this);
//		}
	}

	@Override
	public void onRenderAlpha(FBOS defer, Camera camera, Float value) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void onRender(Camera camera, Float value) {
		throw new UnsupportedOperationException();
	}

	protected void renderCells(HexMapCellShader cellShader) {
		getMapCellVAO().bind();
		MapCell[] cols = null;
		for(int row = 0; row < getCells().length; row ++) {
			cols = getCells()[row];
			for(int col = 0; col < cols.length; col ++) {
				cols[col].render(this, cellShader);
			}
		}
	}
	
	protected void renderDevices(HexMapCreviceShader creviceShader) {
		getMapCreviceVAO().bind();
		for(int i=0; i<getCrevices().length; i++) {
			getCrevices()[i].render(this, creviceShader);
		}
	}
	
	protected void renderTriangles(HexMapTriangleShader triangleShader) {
		getMapTriangleVAO().bind();
		for(int i=0; i<getTriangles().length; i++) {
			getTriangles()[i].render(this, triangleShader);
		}
	}
	
	protected void renderWaters(HexMapWaterShader waterShader) {
		getMapWaterVAO().bind();
		for(int i=0; i<getWaters().length; i++) {
			getWaters()[i].render(this, waterShader);
		}
	}

	protected MapModelChunk createMapModelChunk(int row, int col, int rounds) {
		// TODO Auto-generated method stub
		return null;
	}
	
	protected MapModelChunk createMapModelChunk(Vector3f position, int rounds) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public CollisionShape createCollisionShape() {
		// TODO Auto-generated method stub
		return null;
	}

	public MapCellVAO getMapCellVAO() {
		return mapCellVAO;
	}

	public MapCreviceVAO getMapCreviceVAO() {
		return mapCreviceVAO;
	}

	public MapTriangleVAO getMapTriangleVAO() {
		return mapTriangleVAO;
	}

	public MapWaterVAO getMapWaterVAO() {
		return mapWaterVAO;
	}

	public MapCell[][] getCells() {
		return cells;
	}

	public MapCrevice[] getCrevices() {
		return crevices;
	}

	public MapTriangle[] getTriangles() {
		return triangles;
	}

	public MapWater[] getWaters() {
		return waters;
	}

	public TerrainModelCreator getTerrainModelCreator() {
		return terrainModelCreator;
	}

	public SkyBox getSkybox() {
		return skybox;
	}

}
